package com.zjl.学习.第06章_块步骤_读操作写.C_ItemWriter写;

import com.zjl.学习.第06章_块步骤_读操作写.User;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.database.JdbcBatchItemWriter;
import org.springframework.batch.item.database.builder.JdbcBatchItemWriterBuilder;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.FlatFileItemWriter;
import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder;
import org.springframework.batch.item.file.builder.FlatFileItemWriterBuilder;
import org.springframework.batch.item.json.GsonJsonObjectMarshaller;
import org.springframework.batch.item.json.JacksonJsonObjectMarshaller;
import org.springframework.batch.item.json.JsonFileItemWriter;
import org.springframework.batch.item.json.builder.JsonFileItemWriterBuilder;
import org.springframework.batch.item.support.CompositeItemWriter;
import org.springframework.batch.item.support.builder.CompositeItemWriterBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.PathResource;

import javax.sql.DataSource;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.List;

/**
 * 有输入那肯定有输出，前面讲了输入ItemReader，接下来就看本篇的输出器：
 *      ItemWriter，
 *      Spring Batch提供的数据输出组件与数据输入组件是成对，也就是说有啥样子的输入组件，就有啥样子的输出组件。
 * @see com.zjl.学习.第06章_块步骤_读操作写.A_ItemReader块读
 *
 */
@SpringBootApplication
@EnableBatchProcessing
public class A0_ItemWriter {
    @Autowired//@EnableBatchProcessing 这个注解帮你从 spring batch 的配置文件中加载了
    private JobLauncher jobLauncher;//Job 启动器
    @Autowired
    private JobBuilderFactory jobBuilderFactory;
    @Autowired
    private StepBuilderFactory stepBuilderFactory;
    @Bean
    public FlatFileItemReader<User> itemReaderC(){
        return new FlatFileItemReaderBuilder<User>()
                .name("itemReaderC")
                .resource(new ClassPathResource("item/user_write.txt"))  //指定读取的文件
                .delimited().delimiter("#")  //读取出一行数据，该如何分割数据，默认以,分割，当前使用#号分割
                .names("id", "name", "age")//给分割后数据打name标记，后续跟User对象属性进行映射
                .targetType(User.class)      //读取出一行数据封装成什么对象
                .build();
    }


    @Bean
    public FlatFileItemWriter<User> itemWriter写入平面文件(){
        return new FlatFileItemWriterBuilder<User>()
                .name("itemWriter写入平面文件")
                //输出的文件,不能输出到开发平台的 resources 中，输出到 红色的  target/classes 资源下的文件中了，他不能创建，必须存在才能操作
                .resource(new ClassPathResource("item\\out_User.txt"))
                .resource(new PathResource("D:\\work\\gitee\\spring-batch\\file\\batch\\outUser.txt"))  //输出全路径文件
                .formatted()  //数据格式指定
                .format("id: %s,姓名：%s,年龄：%s")  //输出数据格式
                .names("id", "name", "age")  //需要输出属性
                .shouldDeleteIfEmpty(true)   //如果读入数据为空，输出时创建文件直接删除
                .shouldDeleteIfExists(true)  //如果输出文件已经存在，则删除
                .append(true)  //如果输出文件已经存在， 不删除，直接追加到现有文件中
                .build();
    }

    @Bean//输出成  Json 的方法  明确指定Json格式装配器
    public JacksonJsonObjectMarshaller<User> JacksonToJson(){
        JacksonJsonObjectMarshaller marshaller = new JacksonJsonObjectMarshaller();
        return marshaller;
    }

    @Bean//输出成  Json 的方法  明确指定Json格式装配器  使用 gson 需要进入相关的包
    public GsonJsonObjectMarshaller<User>  gsonToJson(){
        GsonJsonObjectMarshaller marshaller = new GsonJsonObjectMarshaller();
        return marshaller;
    }
    @Bean//输出成json
    public JsonFileItemWriter<User> itemWriterToJson(){
        return new JsonFileItemWriterBuilder<User>()
                .name("jsonUserItemWriter")
                .resource(new PathResource("D:\\work\\gitee\\spring-batch\\file\\batch\\Jackson_outUser.json"))
                .jsonObjectMarshaller(JacksonToJson())//使用哪种输出器

                .resource(new PathResource("D:\\work\\gitee\\spring-batch\\file\\batch\\gson_outUser.json"))
                .jsonObjectMarshaller(gsonToJson())//使用哪种输出器  gson 为空的值不输出

                .build();
    }

    @Autowired//数据源
    private DataSource dataSource;
    @Bean//指定 变量的 值的序号
    public UserPreStatementSetter preStatementSetter(){
        return new UserPreStatementSetter();
    }
    @Bean
    public JdbcBatchItemWriter<User> itemWriterSql(){
        return new JdbcBatchItemWriterBuilder<User>()
                .dataSource(dataSource)
                .sql("insert into employee(id, name, age ,sex) values(?,?,?,?)")
                .itemPreparedStatementSetter(preStatementSetter())//
                .build();
    }
    @Bean//使用多种输出，都输出
    public CompositeItemWriter<User> compositeItemWriter(){
        return new CompositeItemWriterBuilder<User>()
                .delegates(Arrays.asList(itemWriter写入平面文件(), itemWriterToJson(), itemWriterSql()))
                .build();
    }

    @Bean
    public Step stepItemC() throws Exception {
        return stepBuilderFactory.get("stepItemC")
                .<User, User>chunk(2)//执行多少次读处理，再进行写
                .reader(itemReaderC())//读
                .writer(itemWriter写入平面文件())//写入平面文件
                .writer(itemWriterSql())//写入数据库
                .writer(itemWriterToJson())//写入json
                .writer(compositeItemWriter())//组合,可以放入各种输出形式
                .build()
                ;
    }
    @Bean
    public Job jobItemC() throws Exception {
        return jobBuilderFactory.get("jobItemC")
                .start(stepItemC())
                .incrementer(new RunIdIncrementer())
                .build();
    }
    public static void main(String[] args) {
        System.setProperty("spring.profiles.active","01");//  同理 --spring.profiles.active=xxx
        SpringApplication.run(A0_ItemWriter.class, args);
        System.out.println("***********启动完毕**当前编码:" + Charset.defaultCharset().name() + "****************");

    }
}
